package com.anlia.progressbar;

import com.anlia.utils.AttrUtils;
import com.anlia.utils.DpOrPxUtils;

import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.*;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

public class CircleBarView extends Component implements Component.DrawTask, Component.EstimateSizeListener {
    private static final int ARC_ING = 360;
    private static final int MAX = 100;
    private static final double TWO = 2;
    private Paint bgPaint; // 绘制背景圆弧的画笔
    private Paint progressPaint; // 绘制圆弧的画笔

    private RectFloat mRectF; // 绘制圆弧的矩形区域

    private float progressNum; // 可以更新的进度条数值
    private float maxNum; // 进度条最大值

    private Color progressColor; // 进度条圆弧颜色
    private Color bgColor; // 背景圆弧颜色
    private float startAngle; // 背景圆弧的起始角度
    private float sweepAngle; // 背景圆弧扫过的角度
    private float barWidth; // 圆弧进度条宽度
    private AnimatorValue animatorValue;
    private int defaultSize; // 自定义View默认的宽高
    private float progressSweepAngle; // 进度条圆弧扫过的角度
    private float mPlan;

    private Text text;
    private OnAnimationListener onAnimationListener;

    /**
     * 构造
     *
     * @param context 上下文
     */
    public CircleBarView(Context context) {
        this(context,null);
    }

    /**
     * 构造
     *
     * @param context 上下文
     * @param attrSet 属性集
     */
    public CircleBarView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        addDrawTask(this);
        setEstimateSizeListener(this);
        init(context,attrSet);
    }

    private void init(Context context, AttrSet attrs) {
        progressColor = AttrUtils.getColor(attrs, "progress_color", Color.GREEN);
        bgColor = AttrUtils.getColor(attrs,"bg_color",Color.GRAY);
        startAngle = AttrUtils.getFloat(attrs, "start_angle", 0);
        sweepAngle = AttrUtils.getFloat(attrs,"sweep_angle",ARC_ING);
        barWidth = AttrUtils.getDimensionPixelSize(attrs,"bar_width", DpOrPxUtils.dip2px(context,10));

        progressNum = 0;
        maxNum = MAX;
        defaultSize = DpOrPxUtils.dip2px(context,MAX);
        mRectF = new RectFloat();
        progressPaint = new Paint();
        progressPaint.setStyle(Paint.Style.STROKE_STYLE); // 只描边，不填充
        progressPaint.setColor(progressColor);
        progressPaint.setAntiAlias(true); // 设置抗锯齿
        progressPaint.setStrokeWidth(barWidth);
        progressPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP); // 设置画笔为圆角

        bgPaint = new Paint();
        bgPaint.setStyle(Paint.Style.STROKE_STYLE); // 只描边，不填充
        bgPaint.setColor(bgColor);
        bgPaint.setAntiAlias(true); // 设置抗锯齿
        bgPaint.setStrokeWidth(barWidth);
        bgPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        progressSweepAngle = mPlan * sweepAngle * progressNum / maxNum;
        if (text != null) {
            text.setText(onAnimationListener.howToChangeText(mPlan, progressNum, maxNum));
        }
        if (onAnimationListener != null) {
            onAnimationListener.howTiChangeProgressColor(progressPaint, mPlan, progressNum, maxNum);
        }
        Arc arc = new Arc();
        arc.setArc(startAngle, sweepAngle, false);
        Arc mTwoArc = new Arc();
        mTwoArc.setArc(startAngle, progressSweepAngle, false);
        canvas.drawArc(mRectF, arc, bgPaint);
        canvas.drawArc(mRectF, mTwoArc, progressPaint);
    }

    @Override
    public boolean onEstimateSize(int width, int height) {
        int mHeight = measureSize(defaultSize,height);
        int mWidth = measureSize(defaultSize, width);
        int min = Math.min(mWidth, mHeight);
        setEstimatedSize(min,min);
        if (min >= barWidth * TWO) {
            mRectF.fuse((float) (barWidth / TWO),(float)(barWidth / TWO),(float) ((double)min - barWidth / TWO),(float)((double)min - barWidth / TWO));
        }
        return false;
    }

    private int measureSize(int size, int measureSpec) {
        int result = size;
        int specMode = EstimateSpec.getMode(measureSpec);
        int specSize = EstimateSpec.getSize(measureSpec);
        if (specMode == EstimateSpec.PRECISE) {
            result = specSize;
        } else if (specMode == EstimateSpec.NOT_EXCEED) {
            result = Math.min(result, specSize);
        }
        return result;
    }

    public interface OnAnimationListener {
        /**
         * 如何处理要显示的文字内容
         *
         * @param interpolatedTime 从0渐变成1,到1时结束动画
         * @param updateNum 进度条数值
         * @param maxNum 进度条最大值
         * @return text进度
         */
        String howToChangeText(float interpolatedTime, float updateNum, float maxNum);

        /**
         * 如何处理进度条的颜色
         *
         * @param paint 进度条画笔
         * @param interpolatedTime 从0渐变成1,到1时结束动画
         * @param updateNum 进度条数值
         * @param maxNum 进度条最大值
         */
        void howTiChangeProgressColor(Paint paint, float interpolatedTime, float updateNum, float maxNum);
    }

    /**
     * 设置进度
     *
     * @param num 进度
     * @param time 时间
     */
    public void setProgressNum(float num, int time) {
        this.progressNum = num;
        if (animatorValue == null) {
            animatorValue = new AnimatorValue();
            animatorValue.setDuration(time);
        }
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animator, float value) {
                mPlan = value;
                invalidate();
            }
        });
        animatorValue.start();
    }

    /**
     * 接口回调
     *
     * @param onAnimationListener 回调
     */
    public void setOnAnimationListener(OnAnimationListener onAnimationListener) {
        this.onAnimationListener = onAnimationListener;
    }

    /**
     * 设置显示文字的Text
     *
     * @param text 文本
     */
    public void setText(Text text) {
        this.text = text;
    }

    /**
     * 设置进度条最大值
     *
     * @param maxNum 进度最大值
     */
    public void setMaxNum(float maxNum) {
        this.maxNum = maxNum;
    }
}
